Weekly Check In/
Download .zip

Start Recording

Today’s Agenda


  • Weekly Check In
  • Review / Foundational Skills
    • “squished plots”
    • plotly
  • Basic Principles
  • theme() + text
  • scale_*_*
  • Text geom_*()s
  • Fonts
  • Collaborative Practice
  • Mini-Project #2
  • Looking Ahead

Norms


In person norms And also, for online learning…
Be fully present to each other & the work. Keep your video on when possible. In large groups, mute your microphone when not talking. Close/mute/minimize other apps and devices to avoid distraction.
Assume positive intent & also take responsibility for the impact you have. Remember online interaction masks even more of the full story. Notice when you are making assumptions, and seek information to check them.
Embrace collaboration. Use the gallery view so you can see everyone. Use breakout groups as an opportunity to collaborate.
Be open to learning and accept non-closure. Expect the inevitable technical glitches and learning curves. Exercise patience with one another.
Be aware of when to step up and step back. When stepping back, do so as an active listener. Try out different modes of participation. Step back by making space for others to engage in these.
Land your plane–get to the point you intended. We all know how hard it is to be talked at, especially in a Zoom session, so let’s keep it to a minimum.

Review / Foundational Skills

“Squished Plots”


  • Some of your have been experiencing “squished” plots
    • Often happens when you have a plots with lots of panels (facets), or combined plots with {patchwork} and {cowplot}

“Squished Plots”


  • How can you fix this?
    1. In YAML Header:
    • Added out-width: “100%”
      • Makes plots the full width of the document (default is 80%)
---
title: "Untitled"
author: "Fabulous Student"
date: "2025-10-16"
format:
  html:
    embed-resources: true
execute:
    warning: false
    message: false
    out-width: "100%"
---

“Squished Plots”


  • How can you fix this?
    1. In code cell where you create the plot:
#| fig-width: 8
#| fig-height: 6

p <- tidykids |>
  filter(year == 2016,
         expenditure %in% c("PK12ed","SNAP")) |>
  pivot_wider(names_from = expenditure, values_from = inf_adj_perchild) |>
  ggplot(aes(x= SNAP, y= PK12ed)) +
  geom_point(color = "blue")

p
---
  • Can also set this in the YAML header (under embed-resources) to change the default size and not have to do it in each code cell

Mini Project #1

Mini Project #1


  • Great work!
  • Lots of really nice plots
  • Some notes:
    • {ggplot2} automatically drops NAs (you don’t have to filter them out)
    • When showing amounts, also show variability!
    • Clarity in answering your research question is key
      • Plot “fanciness” far less important than clarity!

Mini Project #1 & {plotly}


  • {plotly} is a package that can make your ggplot interactive
  1. Make the plot first
  2. Store it to an object like p
  3. Call ggploty(p)
p <- tidykids |>
  filter(year == 2016,
         expenditure %in% c("PK12ed","SNAP")) |>
  select(-raw,-inf_adj) |>
  pivot_wider(names_from = expenditure, values_from = inf_adj_perchild) |>
  ggplot(aes(x= SNAP, y= PK12ed)) +
  geom_point(color = "blue")

p

Mini Project #1 & {plotly}


  • {plotly} is a package that can make your ggplot interactive
  1. Make the plot first
  2. Store it to an object like p
  3. Call ggploty(p)
#install.packages("plotly")
library(plotly)

p <- tidykids |>
  filter(year == 2016,
         expenditure %in% c("PK12ed","SNAP")) |>
  select(-raw,-inf_adj) |>
  pivot_wider(names_from = expenditure, values_from = inf_adj_perchild) |>
  ggplot(aes(x= SNAP, y= PK12ed)) +
  geom_point(color = "blue") +
  scale_x_continuous(labels = scales::label_currency()) +
  scale_y_continuous(labels = scales::label_currency())

ggplotly(p)

Mini Project #1 & {plotly}


  • {plotly} is a package that can make your ggplot interactive
  1. Make the plot first
  2. Store it to an object like p
  3. Call ggploty(p)
#install.packages("plotly")
library(plotly)

p <- tidykids |>
  filter(year == 2016,
         expenditure %in% c("PK12ed","SNAP")) |>
  select(-raw,-inf_adj) |>
  pivot_wider(names_from = expenditure, values_from = inf_adj_perchild) |>
  ggplot(aes(x= SNAP, y= PK12ed, text = paste0("State: ", state, "<br>SNAP: ", SNAP,
                                               "<br>PK12Ed: ", PK12ed))) +
  geom_point(color = "blue") +
  scale_x_continuous(labels = scales::label_currency()) +
  scale_y_continuous(labels = scales::label_currency())

ggplotly(p, tooltip = "text")

Mini Project #1 & {plotly}


  • {plotly} is a package that can make your ggplot interactive
  1. Make the plot first
  2. Store it to an object like p
  3. Call ggploty(p)
#install.packages("plotly")
library(plotly)

p <- tidykids |>
  filter(year == 2016,
         expenditure %in% c("PK12ed","SNAP")) |>
  select(-raw,-inf_adj) |>
  pivot_wider(names_from = expenditure, values_from = inf_adj_perchild) |>
  ggplot(aes(x= SNAP, y= PK12ed, text = paste0("State: ",state,"<br>SNAP: ",
                                               scales::dollar(SNAP),"<br>PK12Ed: ",
                                               scales::dollar(PK12ed)))) +
  geom_point(color = "blue") +
  scale_x_continuous(labels = scales::label_currency()) +
  scale_y_continuous(labels = scales::label_currency())

ggplotly(p, tooltip = "text")

Recap & Continuing Today…

{ggplot2} is our canvas


Text and Visualization


“Make words and visuals work together effectively — not just showing the data, but explaining the data; helping readers become more visually literate, and reinforcing the main messages the graphic is displaying.”

— Alberto Cairo

Text and Visualization


Cairo uses this example of a “rich” plot in his book How Charts Lie:

  • There is a title and a subtitle
  • There is a easy to understand legend
  • There are defined x- and y-axes
  • There is an annotation
  • There is a caption
  • All text is horizontal (the way we naturally read)

Using Christiansen and France


  • Christiansen, Ch. 9 (2023) and France (2020) provide several suggestions for typographic choices for visualizing data
  • In groups, we will choose ONE style guide and compare it to Christiansen and France
    • Find your group document on Canvas
    • Choose your style guide from the list
    • Review it
    • Compare its components to Christiansen and France
    • If you have enough time, compare the guide you chose to another from the list
  • Choose a spokesperson to report back!
    BREAKOUT ROOMS (10-15 min)

AAUP Data Today


  • Same data as last week
#remotes::install_github("tidyverse/dsbox")
library(dsbox)

staff <- dsbox::instructors

staff_long <- staff |>
  pivot_longer(cols = -year,
               names_to = "position",
               values_to = "proportion") |>
  mutate(date = as.Date(paste0(year, "-01-01")))

staff_long
# A tibble: 55 × 4
    year position                   proportion date      
   <dbl> <chr>                           <dbl> <date>    
 1  1975 full_time_tenured                29   1975-01-01
 2  1975 full_time_tenure_track           16.1 1975-01-01
 3  1975 full_time_non_tenure_track       10.3 1975-01-01
 4  1975 part_time                        24   1975-01-01
 5  1975 grad_student                     20.5 1975-01-01
 6  1989 full_time_tenured                27.6 1989-01-01
 7  1989 full_time_tenure_track           11.4 1989-01-01
 8  1989 full_time_non_tenure_track       14.1 1989-01-01
 9  1989 part_time                        30.4 1989-01-01
10  1989 grad_student                     16.5 1989-01-01
# ℹ 45 more rows

Creating a Plot - Column Chart


p <- staff_long |> 
  filter(year == 2011) |>  
  ggplot(aes(x = position, y = proportion, fill = position)) +
  geom_col()

p

Creating a Plot - Custom Palette


library(MetBrewer)

# Chose to reverse the direction of palette as per documentation
p <- p + scale_fill_manual(values = met.brewer("Hokusai1",
                                        direction = -1))

p

Creating a Plot - Adding Some Text


p <- p +
  labs(
    title = "Instructional Staff Employment Proportions in 2011",
    caption = "Source: American Association of University Professors (AAUP)",
    y = "Percentage",
    fill = "Position"
  )

p

Themes + text

Recap: Themes in {ggplot2} anatomy


What does theme() allow us to edit?


The ‘theme’ involves editing the content that supports the data but does not deliver the quantitative information itself: “data ink”.

  • Text
  • Rectangles
  • Lines
  • Draw nothing

theme() allows us to edit data ink


  • Includes text
p <- p + 
  theme(
    panel.grid = element_blank(), #remove lines
    panel.background = element_blank(), #remove rectangles
    axis.title.x = element_blank(), #remove text
    #legend.position = "none" #odd one - take note
  )

p

theme() lets us edit text elements


  • element_text() sets the font size, colour and face of text elements like plot.title.
  • You can control the font family, face, colour, size (in points), hjust, vjust, angle (in degrees) and lineheight.
p <- p +
  theme(axis.text.x = element_text(face="bold", angle = 45, vjust = .5))

theme() lets us edit text elements


p

scale_*_*

scale_*_* functions


  • See the {ggplot} cheatsheet for a list of scale_*_* functions
  • We’ve already used some of these last week to create custom palettes
  • I think of these like a family of functions
    • Common set of core arguments

Editing axes


We can edit the start/end of axes using scale_*_*.

p <- p +
  scale_y_continuous(limits = c(0, 100),
                     breaks = seq(0,100,20),
                     labels = scales::label_percent(scale=1))

p

Editing axes


We can also use scale_*_* to edit the labels on the axes.

p <- p +
  scale_x_discrete(labels = c("full_time_non_tenure_track" = "Full Time Non-Tenure Track", 
                              "full_time_tenure_track" = "Full Time Tenure Track",
                              "full_time_tenured" = "Full Time Tenured",
                              "grad_student" = "Grad Student",
                              "part_time" = "Part Time"))

p

Editing axes


We can also use scale_*_* to edit the labels in the legend.

  • We already used scale_fill_manual() to create a custom palette with {MetBrewer}, so I’m just adding the labels argument in to what we already had.
p <- p +
  scale_fill_manual(values = met.brewer("Hokusai1",
                                        direction = -1),
                    labels = c("full_time_non_tenure_track" = "Full Time Non-Tenure Track", 
                              "full_time_tenure_track" = "Full Time Tenure Track",
                              "full_time_tenured" = "Full Time Tenured",
                              "grad_student" = "Grad Student",
                              "part_time" = "Part Time"))

Editing axes


We can also use scale_*_* to edit the labels in the legend.

p

theme() allows us to edit data ink


  • Now I’ll remove the legend
p <- p + 
  theme(
    legend.position = "none" #odd one - take note
  )

p

Text geom_*s

Recap: Geoms in {ggplot2} anatomy


What do geoms allow us to do?


  • geoms: Geometric objects like points, lines, bars
  • And also, text!
ggplot(mtcars, aes(wt, mpg, label = rownames(mtcars))) + 
  geom_text()

Text geoms


Text geoms are useful for labeling plots. They can be used by themselves as scatterplots or in combination with other geoms, for example, for labeling points or for annotating the height of bars.

  • geom_text() adds text to the plot
  • geom_label() draws a rectangle behind the text
  • annotate() adds labels at specified points

geom_text()


p + geom_text(aes(label = scales::label_percent(scale=1)(proportion)),
              vjust = -0.5,
              size = 3.5)

geom_label()


p + geom_label(aes(label = scales::label_percent(scale=1)(proportion)),
               vjust = -0.5,
               size = 3.5)

annotate()


To add labels at specified points, use annotate() with annotate(geom = "text", ...) or annotate(geom = "label", ...).

p +
  annotate(
    geom = "text",
    label = "Part-time faculty percentage has increased\nfrom x% in 1975 to x% in 2011.",
    x = 5.5,
    y = 60,
    size = 3,
    colour = "#C6473E",
    hjust = "right" #Can give number or specify left, right, center
  )
  • This is when you want to hard code the numbers (e.g., x%) - not recommended

annotate()


What if instead of hard coding our numbers, we calculate it from our data?

pt_pct_1975 <- 
  staff_long |> 
  filter(position == "part_time", year == "1975") |> 
  pull(proportion)

pt_pct_1975
[1] 24
pt_pct_2011 <- 
  staff_long |> 
  filter(position == "part_time", year == "2011") |> 
  pull(proportion)

pt_pct_2011
[1] 41.3

annotate()


p <- p + geom_text(aes(label = scales::label_percent(scale=1)(proportion)),
                vjust = -0.5,
                size = 3.5) +
  annotate(
    geom = "text",
    label = paste0(
      "Part-time faculty percentage has increased\nfrom ",
      scales::label_percent(scale=1)(pt_pct_1975),
      " in 1975 to ",
      scales::label_percent(scale=1)(pt_pct_2011),
      " in 2011."
    ),
    x = 5.5,
    y = 60,
    size = 3,
    colour = "#C6473E",
    hjust = "right"
  )

annotate()


p

{ggtext}

{ggtext}


library(ggtext)

prop_pt <-
  staff_long |>
  mutate(prop = proportion / 100) |>
  filter(year == 2011,
         position == "part_time") |>
  pull(prop)

p <- p +
  labs(
    subtitle = paste0(
      "Part-timers made up <b><span style = 'color:#C6473E;'>",
      scales::label_percent()(prop_pt),
      "</span></b> of faculty in 2011"
    )
  ) +
  theme(plot.subtitle = ggtext::element_markdown()) #Makes the html work!

{ggtext}


p

{ggtext}


  • Can also use {ggtext} to remove need for legend

{ggtext}


labs(y = "Marginal Effects", title = "Marginal Effects of 
<b><span style = 'color: #D8A419;'>City</span></b>,
<b><span style = 'color: #7B8400;'>Town</span></b>,
<b><span style = 'color: #C61A72;'>Rural:Fringe</span></b>,
<b><span style = 'color: #D65E9B;'>Rural:Distant</span></b>, & 
<b><span style = 'color: #EDBAD4;'>Rural:Remote</span></b>
Locale on AP® STEM Success<br><i>Comparison: Suburb</i>")

Fonts

family aesthetic


  • The family aesthetic provides the name of a font. This aesthetic does allow you to use the name of a system font, but some care is required.
  • There are only three fonts that are guaranteed to work everywhere: “sans” (the default), “serif”, or “mono”.
p <- p +
  theme(plot.title = element_text(size = 18,
                                  family = "serif"))

family aesthetic


p

Using other fonts


Text drawing is handled differently by each graphics device (GD):

  • windows() (for Windows)
  • quartz() (for Macs)
  • x11() (mostly for Linux)
  • RStudioGD() within RStudio

The devices do not specify fonts in the same way, so if you want a font to work everywhere you need to configure the devices in different ways.

Using other fonts


Two packages simplify fonts a bit:

Using Google fonts with {showtext}


  • font_add_google(name, family) adds a font
    • name is the name of the font searched in Google Fonts
    • family is the name you assign
  • The showtext_auto() function tells R to render text using {showtext}

Using Google fonts with {showtext}


Changing text edits the font family for the plot fonts.

library(showtext)

font_add_google(name = "Open Sans", family = "open-sans")

showtext_auto() #necessary for it to work

p <- p +
  theme(text = element_text(size = 9,
                            family = "open-sans"))

Tip

You may need to install additional packages for font_add_google(). On Windows, be prepared to install {jsonlite} and {curl}.

Using Google fonts with {showtext}


  • Why didn’t the title change? Everything else worked…
p

Using Google fonts with {showtext}


You can specify fonts for different plot elements, as well.

font_add_google(name = "Schoolbell", family = "bell")

p <- p +
  theme(plot.title = element_text(size = 18,
                                  family = "bell"))
# Note I could have specified "open-sans" here to fix the earlier issue.

Using Google fonts with {showtext}


p

Using custom fonts with {showtext}


font_add() adds a font file like .ttf

  • family is the family name of the font
  • regular is the font file path
font_add(family = "Asenine",
         regular = here::here("week-9", "ASENINE_.ttf"))

p <- p +
  theme(plot.title = element_text(size = 18,
                                     family = "Asenine"))

Using custom fonts with {showtext}


p

Other helpful packages for text


  • {ggrepel} - repel overlapping text labels
  • {ggforce} - extends {ggplot2} in various ways
  • {gghighlight} - direct labeling in {ggplot2}
  • {ggfittext} - fit text into boxes
  • {directlabels} - puts labels close to data

Accessibility


  • Sufficient labels
  • Do not rely on color alone
  • Label significant parts of the graph
  • Use labels and legends that clearly mark and distinguish the data points

BREAK

Collaborative Practice


  • You will do Steps 3-5.
    • 1,2, & 6 have been done for you.
  • Launch into breakout rooms.
  • Cameras off: 3-5 min to review task
  • Cameras on: collaborative task work
  • Individual option

Mini-Project #2

Looking Ahead


  • Reading:
    • Chang (2024), Ch. 7
    • Chang (2024), Ch. 11
    • R Coder (2024)
  • Assignment: Begin work on mini-project #2
  • Assignment: Individually complete collaborative practice if not finished